export class OBCanvas2D {
    /**
     * @type {HTMLCanvasElement}
     */
    canvas;
    /**
     * @type {CanvasRenderingContext2D}
     */
    canvas2dctx;
    /**
     *
     * @param {HTMLCanvasElement} canvas
     */
    constructor(canvas) {
        this.canvas = canvas;
        this.canvas2dctx = canvas.getContext('2d');
    }
    setFillStyleColor(color) {
        let str_color;
        if (color < 0) {
            str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8)
            str_color = '#' + str_color;
        } else {
            str_color = '#' + color.toString(16).padStart(8, '0');
        }
        this.canvas2dctx.fillStyle = str_color.substr(0,7);
    }
    /**
     * 安装到脚本库
     * @param {OBScript} script
     */
    install(script) {
        let self = this;
        script.InstallLib("canvas2d", "canvas2d", [
            self.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']),
            self.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']),
            // canvas2dctx.fillStyle=color
            self.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']),
            self.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']),
            self.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'LongRegister', 'LongRegister']),
            self.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []),
            self.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']),
            self.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []),
            self.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []),
            self.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'),
            self.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'),
        ]);
    }
    fieldSetter(target, fieldName, register) {
        return (builder, args) => {
            let getter = builder[register][args[1] & 0xfff];
            builder.PushAction((st, f, local, pos) => {
                let v = getter(st, f, local);
                target[fieldName] = v;
                return 1 + pos;
            });
        };
    }
    fieldGetter(target, fieldName, register) {
        return (builder, args) => {
            builder[register][args[1] & 0xfff] = (st, f, local) => {
                return target[fieldName];
            };
        };
    }
    /**
     *
     * @param {Function} func
     * @param {Number[]} argtype
     * @returns
     */
    closureVoid(func, argtype) {
        /**
         * 
         * @param {OBFunctionBuilder} builder 
         * @param {Number[]} args 
         * @returns 
         */
        let f = (builder, args) => {
            args = args.slice(1);
            let argGetters = argtype.map((rtype, idx) => {
                let idx1 = args[idx] & 0xFFF;
                let v = builder[rtype][idx1];
                return (st, f, local) => {
                    return v(st, f, local);
                };
            });
            builder.PushAction((st, f, local, pos) => {
                let argVals = argGetters.map(g => g(st, f, local));
                func.apply(null, argVals);
                return pos + 1;
            });
        };
        return f;
    }
}